package cn.com.bluemoon.daps.model.core.file.excel.listener;

import cn.com.bluemoon.daps.common.exception.DapException;
import cn.com.bluemoon.daps.model.core.file.FieldData;
import cn.com.bluemoon.daps.model.core.file.config.GlobalParserConfig;
import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.DbType;
import com.alibaba.excel.context.AnalysisContext;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import static cn.com.bluemoon.daps.common.constant.DapConstant.DapModel.HIVE_COMPLEX_TYPES;
import static org.apache.commons.lang.StringUtils.lowerCase;

/**
 * 有个很重要的点 FieldDataListener 不能被spring管理，要每次读取excel都要new,然后里面用到spring可以构造方法传进去
 *
 * @author Jarod.Kong
 */
@Slf4j
public class FieldDataListener extends BaseDataListener<FieldData> {
    private static final HashMap<DbType, String> FIELD_DB_HEADER = new HashMap<DbType, String>(6) {{
        put(DbType.mysql, generateHeadNameStr(Arrays.asList("序号", "表英文名", "字段名", "数据类型", "长度", "小数位", "主键", "非空", "缺省", "是否自增", "初始值", "无符号", "填充零", "字段中文名", "字段业务描述")));
        put(DbType.postgresql, generateHeadNameStr(Arrays.asList("序号", "表英文名", "字段名", "数据类型", "长度", "小数位", "主键", "非空", "缺省", "字段中文名", "字段业务描述")));
        put(DbType.hive, generateHeadNameStr(Arrays.asList("序号", "表英文名", "字段名", "数据类型", "复合类型定义", "长度", "小数位", "字段中文名", "字段业务描述")));
    }};

    public FieldDataListener(GlobalParserConfig globalParserConfig) {
        super(globalParserConfig);
    }

    /**
     * @return 获取数据库对应的表头信息
     */
    @Override
    protected Map<DbType, String> getDbTypeExcelStandardHeader() {
        return FIELD_DB_HEADER;
    }

    @Override
    public void rowDataValidate0(FieldData data, AnalysisContext context) {
        String dataKey = generateDataLowCaseKey(data.getTableName(), data.getFieldName());
        data.setKey(dataKey);
        boolean preT = checkExcelRepeatMap.contains(data.getKey());
        if (preT) {
            data.getErrorMsgs().add("表字段英文名重复");
            data.setFail(true);
            noValidExcelDataCollector.add(data);
        }
        // 增加hive的复合类型校验
        if (DbType.hive.equals(dbType) && HIVE_COMPLEX_TYPES.containsKey(lowerCase(data.getFiledDataType()))) {
            if (StrUtil.isBlank(data.getCompoundType())) {
                data.setFail(true);
                data.getErrorMsgs().add("Hive字段的数据类型为复合类型，复合类型定义不可为空！！");
                log.error("表{}-Hive字段的数据类型为复合类型，复合类型定义不可为空！！", data.getKey());
                noValidExcelDataCollector.add(data);
            }
        }
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        DapException dapException = exception instanceof DapException ? ((DapException) exception) : null;
        if (dapException != null) {
            throw new DapException(dapException.getMessage());
        }
        throw exception;
    }

    /**
     * 定义数据大小，针对表、字段、索引可以重写调整
     *
     * @return 定义数据大小，针对表、字段、索引可以重写调整
     */
    @Override
    protected int dataMapInitialCapacity() {
        return 1024 * 10;
    }
}
